﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using RssReader.DataModel;
using RssReader.FeedsProvider;
using Windows.Data.Html;
using Windows.Web.Syndication;

namespace RssReader.FeedProvider
{
    public class RssFeedProvider : IFeedProvider
    {
        static private readonly Dictionary<string,SyndicationFeed> SyndicationCache = new Dictionary<string, SyndicationFeed>();
        private const string SyndicationfeedKey = "syndicationFeed";        
        public RssFeedProvider()
        {
        }

        public RssFeedProvider(bool clearCache)
        {
            if (clearCache && SyndicationCache.ContainsKey(SyndicationfeedKey)) SyndicationCache.Remove(SyndicationfeedKey);
        }

    
        public async Task<Feed> Get_feed(string url, string category, int maxItems, Category categoryCollection)
        {
            var feeds = new Feed();
            
            var feed = await Syndication_feed(url,category);

            var topFeeds = feed.Items.OrderByDescending(x =>
                                                        x.PublishedDate).ToList();
            feeds.Title = feed.Title.Text;
            feeds.Url = url;
            feeds.Category = category;
            feeds.TotalItems = feed.Items.Count;

            Convert_syndicationitem_to_feed_item(categoryCollection, feeds, topFeeds);
            return feeds;
        }

        public void Convert_syndicationitem_to_feed_item(Category category, Feed feed, List<SyndicationItem> syndicationItems)
        {
            foreach (var item in syndicationItems)
            {
                if (item.Summary == null) continue;

                var feedItem = new Item {Title = item.Title.Text, Published_on = item.PublishedDate.DateTime};
                var authors = from a in item.Authors
                              select a.Name;
                feedItem.Author =
                    String.Join(",", authors);
                feedItem.Content = item.Content !=
                                   null
                                       ? HtmlUtilities.ConvertToText(item.Content.Text)
                                       : String.Empty;
                
                    feedItem.Description = item.Summary !=
                                           null
                                               ? HtmlUtilities.ConvertToText(item.Summary.Text)
                                               : HtmlUtilities.ConvertToText(item.Content.Text);
                var imageFromFeedItemContent = Get_image_from_feed_item_content(item.NodeValue);
                feedItem.Image_path = imageFromFeedItemContent;
                feedItem.Title_fontsize = 20;
                feedItem.Height = 60;
                if (!string.IsNullOrEmpty(imageFromFeedItemContent))
                {
                    
                    feedItem.Title_fontsize = 18;
                    
                }

                var links = from link in item.Links
                            select new Link(link.Uri.ToString(), link.Title);
                feedItem.Links = links.ToList();
                feedItem.Category = category;
                feed.Items.Add(feedItem);
                
            }
            feed.Items = feed.Items.OrderByDescending(id => !string.IsNullOrEmpty(id.Image_path)).ToList();
            Layout_items(feed);
        }

        private static void Layout_items(Feed feed)
        {
            int iLoop = 0;
            var rowspans = new[] {2, 2, 2, 2, 2, 2, 2, 4, 4, 2};
            var colspans = new[] {2, 3, 2, 2, 2, 3, 2, 2, 1, 2};

            foreach (var itemInFeed in feed.Items)
            {
                if (string.IsNullOrEmpty(itemInFeed.Image_path))
                {
                    itemInFeed.Column_span = 1;
                    itemInFeed.Row_span = 2;
                    continue;
                }
                itemInFeed.Column_span = colspans[iLoop];
                itemInFeed.Row_span = rowspans[iLoop];
                if (iLoop >= 9) iLoop = 0;else iLoop++;
            }
        }

        private string Get_image_from_feed_item_content(string nodeValue)
        {
            Match match = Regex.Match(nodeValue, @"(?<=<img\s+[^>]*?src=(?<q>['""]))(?<url>.+?)(?=\k<q>)", RegexOptions.IgnoreCase);
            var imageExtension = new[] {"jpg", ".png", ".bmp"};
            
            string imageUrl = string.Empty;
            if (match.Success)
            {
                // Finally, we get the Group value and display it.
                imageUrl = match.Groups[0].Value;
            }

            Func<string, bool> images = s =>
                                            {
                                                if (imageUrl.EndsWith(s)) return true;

                                                return false;
                                            };

            var boolean = imageExtension.Any(images);

            if (!boolean) return string.Empty;

            return imageUrl;
        }

        public async Task<SyndicationFeed> Syndication_feed(string url, string category)
        {
            var client = new SyndicationClient
                             {
                                 BypassCacheOnRetrieve = true
                             };

            client.SetRequestHeader("user-agent",
                                    "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");

            var feedUri = new Uri(url);
            SyndicationFeed feed;
            var keyExists = false;
            
            foreach (var syndicationFeed in SyndicationCache)
            {
                if (syndicationFeed.Key == category) keyExists = true;
            }
            if (!keyExists)
            {
                feed = await client.RetrieveFeedAsync(feedUri);

                SyndicationCache[category] = feed;   
            }
            else
            {
                feed = SyndicationCache[category];
            }
            return feed;
        }
        
    }
}